/**Universidad del Valle de Guatemala 
 * Algoritmos y Estructura de Datos
 * Dennisse Escobar Delgado
 * Fecha: 20/09/2012
 * Produce la tabla de frecuencia de arboles binarios.  
 * @param <E> 
 */

public class ArbolBinario <E>
{
        //---------------------------------------------
        //ATRIBUTOS 
        //---------------------------------------------
        
        /**
         * Valor del arbol.
         */
    protected E valor;
    
    /**
         * Valor que ocupa el lugar de padre.
         */
    protected ArbolBinario<E> padre;
    
    /**
         * Valor que ocupa el lugar de la izquierda del padre.
         */
    protected ArbolBinario<E> izquierda;
    
    /**
         * Valor que ocupa el lugar de la derecha del padre.
         */
    protected ArbolBinario<E> derecha;

    //----------------------
        //CONSTRUCTOR
        //----------------------
        
        /**
         * Método que construye un nuevo arbol binario
         */
    public ArbolBinario()
    {
        valor = null;
        padre = null;
        izquierda = null;
        derecha = null;
    }

    //----------------------
        //METODOS
        //----------------------
        
        /**
         * Método que construye un arbol binario a partir de un valor
         * @param val Nuevo valor para construir el arbol binario.
         */
    public ArbolBinario(E val)
    {
        valor = val;
        derecha = new ArbolBinario<E>();
        izquierda =  new ArbolBinario<E>();
        izquierda = null;
        derecha = null;
    }

    /**
         * Método que construye un arbol binario a partir de un valor, un arbol izquierdo y uno derecho
         * @param val Nuevo valor.
         * @param izq Arbol binario izquierdo.
         * @param der Arbol binario derecho.
         */
    public ArbolBinario(E val, ArbolBinario<E> izq, ArbolBinario<E> der)
    {
        valor = val;
        if (izq == null)
                izq = new ArbolBinario<E>();
        cambiarIzquierda(izq);
        if (der == null)
                der = new ArbolBinario<E>();
        cambiarDerecha(der);
    }

    /**
         * Método para cambiar el padre.
         * @param p Nuevo padre.
         */
    protected void cambiarPadre(ArbolBinario<E> p)
    {
        padre = p;
    }

    /**
         * Método para cambiar el hijo izquierdo.
         * @param i Nuevo hijo izquierdo.
         */
    public void cambiarIzquierda(ArbolBinario<E> i)
    {
        if (izquierda != null && izquierda.darPadre() == this)
                izquierda.cambiarPadre(null);
        izquierda = i;
        izquierda.cambiarPadre(this);
    }

    /**
         * Método para cambiar el hijo derecho.
         * @param d Nuevo hijo derecho.
         */
    public void cambiarDerecha(ArbolBinario<E> d)
    {
        if (derecha != null && derecha.darPadre() == this)
                derecha.cambiarPadre(null);
        derecha = d;
        derecha.cambiarPadre(this);
    }

    /**
         * Método para cambiar el valor.
         * @param val Nuevo valor.
         */
    public void cambiarValor(E val)
    {
        valor = val;
    }

    /**
         * Método para obtener el padre del arbol.
         * @return Padre del arbol.
         */
    protected ArbolBinario<E> darPadre()
    {
        return(this.padre);
    }

    /**
         * Método para obtener el arbol izquierdo.
         * @return Hijo izquierdo.
         */
    public ArbolBinario<E> darIzquierda()
    {
        return izquierda;
    }

    /**
         * Método para obtener el arbol derecho.
         * @return Hijo derecho.
         */
    public ArbolBinario<E> darDerecha()
    {
        return derecha;
    }

    /**
         * Método para obtener el valor.
         * @return Valor.
         */
    public E darValor()
    {
        return valor;
    }
}